#include "lwip_demo.h"


/* 需要自己设置远程IP地址 */
#define IP_ADDR   "10.89.17.128"

#define LWIP_DEMO_RX_BUFSIZE         100                        /* 最大接收数据长度 */
#define LWIP_DEMO_PORT               2000                       /* 连接的本地端口号 */
#define LWIP_SEND_THREAD_PRIO       ( tskIDLE_PRIORITY + 3 )    /* 发送数据线程优先级 */
/* 接收数据缓冲区 */
uint8_t g_lwip_demo_recvbuf[LWIP_DEMO_RX_BUFSIZE]; 

/* 发送数据内容 */
uint8_t g_lwip_demo_sendbuf[] = "ALIENTEK DATA \r\n";
/* 数据发送标志位 */
uint8_t g_lwip_send_flag;
int g_sock = -1;
int g_lwip_connect_state = 0;
static void lwip_send_thread(void *arg);


/**
 * @brief       发送数据线程
 * @param       无
 * @retval      无
 */
void lwip_data_send(void)
{
    xTaskCreate(lwip_send_thread, "lwip_send_thread", 4096, NULL, LWIP_SEND_THREAD_PRIO, NULL);
}

/**
 * @brief       lwip_demo实验入口
 * @param       无
 * @retval      无
 */
void lwip_demo(void)
{
    struct sockaddr_in atk_client_addr;
    err_t err;
    int recv_data_len;
    
    // lwip_data_send();                                           /* 创建发送数据线程 */
    
    while (1)
    {
        sock_start:
                g_lwip_connect_state = 0;
                atk_client_addr.sin_family = AF_INET;                   /* 表示IPv4网络协议 */
                atk_client_addr.sin_port = htons(LWIP_DEMO_PORT);       /* 端口号 */
                atk_client_addr.sin_addr.s_addr = inet_addr(IP_ADDR);   /* 远程IP地址 */
                g_sock = socket(AF_INET, SOCK_STREAM, 0);               /* 可靠数据流交付服务既是TCP协议 */
                memset(&(atk_client_addr.sin_zero), 0, sizeof(atk_client_addr.sin_zero));
                
                printf("Port:%d", LWIP_DEMO_PORT);       /* 客户端端口号 */
                
                /* 连接远程IP地址 */
                err = connect(g_sock, (struct sockaddr *)&atk_client_addr, sizeof(struct sockaddr));

                if (err == -1)
                {
                    closesocket(g_sock);
                    g_sock = -1;
                    vTaskDelay(10);
                    goto sock_start;
                }
                g_lwip_connect_state = 1;   
        
        while (1)
        {
            // // 设置接收超时（可选）
            // struct timeval timeout = {.tv_sec = 5, .tv_usec = 0}; // 5秒超时
            // setsockopt(g_sock, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));
            
            recv_data_len = recv(g_sock, g_lwip_demo_recvbuf, LWIP_DEMO_RX_BUFSIZE - 1, 0);
            
            if (recv_data_len > 0) 
            {
                // 确保字符串以null结尾
                g_lwip_demo_recvbuf[recv_data_len] = '\0';
                
                // 安全地打印接收到的数据
                printf("Received %d bytes: %s\n", recv_data_len, g_lwip_demo_recvbuf);
            }
            else if (recv_data_len == 0) 
            {
                // 对端正常关闭连接
                printf("Connection closed by peer\n");
                closesocket(g_sock);
                g_sock = -1;
                break; // 跳出循环，而不是用goto
            }
            else 
            {
                // 接收出错
                int error_code = errno;
                printf("recv failed, error: %d (%s)\n", error_code, strerror(error_code));
                
                // 根据错误类型决定是否重连
                if (error_code == ECONNRESET || error_code == ENOTCONN) {
                    closesocket(g_sock);
                    g_sock = -1;
                    break;
                }
            }
            
            vTaskDelay(10 / portTICK_PERIOD_MS);
        }

        // 重新连接逻辑放在循环外部
        if (g_sock == -1) {
            vTaskDelay(1000 / portTICK_PERIOD_MS); // 等待1秒后重连
            // 重新建立连接
        }
    }
}

/**
 * @brief       发送数据线程函数
 * @param       pvParameters : 传入参数(未用到)
 * @retval      无
 */
void lwip_send_thread(void *pvParameters)
{
    pvParameters = pvParameters;
    
    err_t err;
    
    while (1)
    {
        while (1)
        {
            if(((g_lwip_send_flag & LWIP_SEND_DATA) == LWIP_SEND_DATA) && (g_lwip_connect_state == 1)) /* 有数据要发送 */
            {
                err = write(g_sock, g_lwip_demo_sendbuf, sizeof(g_lwip_demo_sendbuf));
                
                if (err < 0)
                {
                    break;
                }
                
                g_lwip_send_flag &= ~LWIP_SEND_DATA;
            }
            
            vTaskDelay(10);
        }
        
        closesocket(g_sock);
    }
}
